Frontend Arka Plan Getirme API'sinin, web uygulamalarında büyük indirme yönetiminde nasıl devrim yarattığını ve küresel kullanıcılar için güvenilir, çevrimdışı özellikli aktarımlar sağladığını keşfedin.
Büyük İndirmelerde Uzmanlaşma: Frontend Arka Plan Getirme API'si için Küresel Bir Rehber
Günümüzün birbirine bağlı dünyasında, web uygulamalarından büyük dosyaların verimli ve güvenilir bir şekilde aktarılması da dahil olmak üzere giderek daha karmaşık görevleri yerine getirmeleri beklenmektedir. İster yüksek çözünürlüklü bir film, ister önemli bir yazılım güncellemesi, bütün bir e-kitap kütüphanesi veya kurumsal bir uygulama için kritik bir veri seti olsun, dünya genelindeki kullanıcılar ağ koşulları veya cihaz kullanım alışkanlıklarından bağımsız olarak sorunsuz deneyimler talep etmektedir. Geleneksel olarak, web'de büyük indirmeleri yönetmek zorluklarla doluydu. Bir sekmeden ayrılan veya anlık bir ağ kesintisi yaşayan bir kullanıcı, uzun süren bir indirmeyi anında tehlikeye atarak hayal kırıklığına ve bant genişliği israfına yol açabilirdi. İşte bu noktada güçlü Frontend Arka Plan Getirme API'si (Frontend Background Fetch API) devreye girerek, web uygulamalarının kalıcı ve büyük ölçekli dosya transferlerini nasıl ele aldığını dönüştüren sağlam bir çözüm sunar.
Bu kapsamlı rehber, Arka Plan Getirme API'sinin derinliklerine inerek temel işlevlerini, pratik uygulamalarını ve en iyi uygulamalarını incelemektedir. Service Worker'ların gücünden yararlanan bu API'nin, geliştiricilere arka planda önemli veri operasyonlarını yönetebilen, gerçekten esnek ve kullanıcı dostu web uygulamaları oluşturma gücünü nasıl verdiğini ve çeşitli küresel ortamlardaki kullanıcılar için deneyimi nasıl geliştirdiğini inceleyeceğiz.
Web'de Büyük İndirmelerin Süregelen Zorluğu
Gelişmiş web yeteneklerinin ortaya çıkmasından önce, frontend geliştiricileri büyük dosya indirmelerini uygulamakla görevlendirildiklerinde önemli engellerle karşılaşıyorlardı. Web'in durumsuz (stateless) doğası ve tarayıcının sanal alan (sandbox) ortamı, güvenlik sunarken, genellikle güvenilir ve uzun süren operasyonları zorlaştıran sınırlamalar getiriyordu. Geleneksel zorlukları daha ayrıntılı olarak inceleyelim:
Tarayıcı Sekmesi Bağımlılığı: Kırılgan Bir Bağlantı
Geleneksel web indirmelerinin en kritik sınırlamalarından biri, aktif bir tarayıcı sekmesine olan doğal bağımlılıklarıdır. Bir kullanıcı bir indirme başlattığında, süreç kaçınılmaz olarak indirme işleminin başlatıldığı sekmeye bağlıydı. Kullanıcı yanlışlıkla sekmeyi kapatırsa, başka bir sayfaya giderse veya hatta farklı bir uygulamaya geçerse, indirme genellikle aniden sonlanırdı. Bu, özellikle tamamlanması dakikalar hatta saatler sürebilen büyük dosyalar için son derece kırılgan bir deneyim yaratıyordu. Yoğun bir uluslararası havaalanında, kesintili Wi-Fi'ye bağlı bir kullanıcının uzun uçuşu için bir film indirmeye çalıştığını hayal edin. Kısa bir sinyal düşüşü veya istemeden sekmeyi kapatma, indirmeyi baştan başlatmak anlamına gelerek zaman ve veri israfına neden oluyordu. Bu bağımlılık sadece bir rahatsızlık değil, aynı zamanda yerel uygulama deneyimleriyle rekabet edebilecek gerçekten sağlam web uygulamaları oluşturmanın önünde temel bir engeldi.
Ağ İstikrarsızlığı: Küresel Gerçeklik
Ağ koşulları dünya genelinde büyük farklılıklar gösterir. Bazı bölgeler yıldırım hızında, istikrarlı internete sahipken, özellikle gelişmekte olan ekonomilerdeki veya kırsal alanlardaki birçok kullanıcı yavaş, güvenilmez veya sık sık kesilen bağlantılarla mücadele etmektedir. Geleneksel HTTP indirmeleri, tarayıcı perspektifinden kısmi indirmeler için doğal bir yeniden deneme mekanizmasından veya akıllı devam etme yeteneklerinden yoksundur (sunucular bunu desteklese de, istemci genellikle durumunu kaybeder). Dünyanın birçok yerinde yaygın olan kısa bir ağ kesintisi, bir indirmeyi kalıcı olarak durdurabilir ve kullanıcının manuel olarak yeniden başlatmasını gerektirebilirdi. Bu sadece kullanıcıları hayal kırıklığına uğratmakla kalmaz, aynı zamanda dünya genelindeki mobil kullanıcılar için yaygın bir senaryo olan tarifeli bağlantılardaysalar gereksiz veri maliyetleri de getirirdi. Ağ dalgalanmalarına karşı dayanıklılık eksikliği, uzun süredir küresel erişim ve erişilebilirlik hedefleyen web geliştiricileri için bir sıkıntı noktası olmuştur.
Kullanıcı Deneyimi Sorunları: Bekleme ve Belirsizlik
Büyük indirmeler için, kullanıcı deneyiminin kritik bir yönü şeffaf ilerleme raporlamasıdır. Kullanıcılar ne kadar indirildiğini, ne kadar kaldığını ve tahmini tamamlanma süresini bilmek ister. Geleneksel tarayıcı indirme yöneticileri bazı temel geri bildirimler sağlar, ancak bunu bir web uygulamasının kullanıcı arayüzüne sorunsuz bir şekilde entegre etmek genellikle karmaşık veya sınırlıydı. Ayrıca, kullanıcıları sadece bir indirmeyi izlemek için bir sekmeyi açık ve aktif tutmaya zorlamak kötü bir kullanıcı deneyimi yaratır. Sistem kaynaklarını meşgul eder, diğer içeriklerle etkileşim kurmalarını engeller ve uygulamanın daha az profesyonel görünmesine neden olur. Kullanıcılar bir görevi başlatmayı ve tarayıcılarını kapatsalar bile arka planda tamamlanacağına güvenmeyi beklerler.
Sınırlı İlerleme Raporlaması ve Kontrol
Tarayıcılar temel indirme ilerlemesi sunsa da, geleneksel indirmeler için web uygulamanızın içinde ayrıntılı, gerçek zamanlı güncellemeler almak zahmetliydi. Geliştiriciler genellikle yoklama (polling) veya karmaşık sunucu tarafı cambazlıklarına başvuruyorlardı ki bu da karmaşıklığı ve ek yükü artırıyordu. Dahası, bir indirme başladıktan sonra kullanıcıların çok az kontrolü vardı. Bir indirmeyi ortasında duraklatmak, devam ettirmek veya iptal etmek genellikle tarayıcının varsayılan indirme yöneticisi tarafından, web uygulamasının özel kullanıcı arayüzü aracılığıyla değil, ya hep ya hiç şeklinde bir operasyondu. Bu programatik kontrol eksikliği, geliştiricilerin sunabileceği indirme yönetimi özelliklerinin gelişmişliğini sınırlıyordu.
Geliştiriciler için Kaynak Yönetimi Yükü
Geliştiriciler için, büyük indirmeleri yönetmek geleneksel olarak bir dizi istisnai durumla başa çıkmak anlamına geliyordu: ağ hatalarını ele almak, yeniden deneme mantığı uygulamak, kısmi dosya durumlarını yönetmek ve veri bütünlüğünü sağlamak. Bu genellikle bakımı ve ölçeklendirilmesi zor, karmaşık ve hataya açık kodlara yol açıyordu. Sıfırdan sağlam indirme özellikleri oluşturmak, özellikle arka planda kalıcılık gerektirenler, temel uygulama geliştirmeden kaynakları saptıran önemli bir mühendislik zorluğuydu. Standartlaştırılmış, tarayıcı düzeyinde bir çözüme olan ihtiyaç açıktı.
Frontend Arka Plan Getirme API'si ile Tanışın
Arka Plan Getirme API'si (Background Fetch API), bu uzun süredir devam eden zorlukları doğrudan ele almak için tasarlanmış modern bir web platformu özelliğidir. Web uygulamalarının, kullanıcı sayfadan ayrıldığında veya tarayıcıyı kapattığında bile arka planda büyük dosya indirmelerini (ve yüklemelerini) başlatması ve yönetmesi için sağlam ve standartlaştırılmış bir yol sağlar. Bu API, Service Worker'ların üzerine inşa edilmiştir ve onların ana tarayıcı iş parçacığından (main thread) bağımsız olarak çalışma ve oturumlar arasında durumu koruma yeteneklerinden yararlanır.
Bu Nedir? (Service Worker Bağlantısı)
Temel olarak, Arka Plan Getirme API'si bir getirme (fetch) işleminin sorumluluğunu bir Service Worker'a devrederek çalışır. Bir Service Worker, tarayıcının arka planda, ana web sayfasından ayrı olarak çalıştırdığı bir JavaScript dosyasıdır. Programlanabilir bir proxy görevi görerek ağ isteklerini engeller, kaynakları önbelleğe alır ve bu bağlamda arka plan görevlerini yönetir. Bir arka plan getirme işlemi başlattığınızda, aslında Service Worker'ınız aracılığıyla tarayıcıya, "Lütfen bu dosyaları güvenilir bir şekilde indirin ve bittiğinde veya bir sorun olursa bana bildirin" demiş olursunuz. Service Worker daha sonra devralır, ağ isteklerini, yeniden denemeleri ve kalıcılığı yönetir, böylece ana iş parçacığını ve kullanıcının aktif oturumunu bu endişelerden kurtarır.
Arka Plan Getirme'nin Temel Faydaları
Arka Plan Getirme API'si, küresel, yüksek performanslı bir deneyim hedefleyen web uygulamaları için birçok dönüştürücü fayda sunar:
- Güvenilirlik: Kullanıcı sekmeyi kapatsa, başka bir yere gitse veya ağ bağlantısını kaybetse bile indirmeler devam eder. Tarayıcının işletim sistemi getirme işlemini yönetir ve sağlam yeniden deneme mekanizmaları sağlar.
- Gelişmiş Kullanıcı Deneyimi: Kullanıcılar büyük indirmeler başlatabilir ve indirmenin arka planda tamamlanacağını bilerek güvenle gezinmeye devam edebilir veya tarayıcılarını kapatabilirler. İlerleme bildirimleri yerel sistem bildirimleri aracılığıyla iletilebilir.
- Çevrimdışı Yetenekler: İndirildikten sonra içerik çevrimdışı olarak kullanılabilir hale getirilebilir, bu da özellikle sınırlı veya internet erişimi olmayan bölgelerdeki medya oynatıcılar, eğitim platformları ve belge görüntüleyiciler gibi uygulamalar için çok önemlidir.
- Ayrıntılı Kontrol: Geliştiriciler, indirme ilerlemesini izlemek, başarı/başarısızlık durumlarını yönetmek ve hatta devam eden getirme işlemlerini doğrudan web uygulamalarından iptal etmek için programatik erişim kazanır.
- Azaltılmış Kaynak Tüketimi: Ağır indirme görevlerini Service Worker'a ve tarayıcının temel ağ yığınına devrederek, ana iş parçacığı duyarlı kalır ve genel uygulama performansını artırır.
- Aşamalı Geliştirme (Progressive Enhancement): Geliştiricilerin, desteklendiği yerlerde üstün bir deneyim sunmasına olanak tanırken, API'yi henüz uygulamamış tarayıcılar için zarif bir geri çekilme (fallback) sağlar.
Temel Kavramlar: BackgroundFetchManager, BackgroundFetchRegistration, BackgroundFetchEvent
Arka Plan Getirme API'sini etkili bir şekilde kullanmak için, birincil bileşenlerini anlamak esastır:
-
BackgroundFetchManager: Bu,navigator.serviceWorker.ready.then(registration => registration.backgroundFetch)aracılığıyla erişilebilen API'nin giriş noktasıdır. Yeni arka plan getirme işlemleri başlatmanıza ve mevcut olanlar hakkında bilgi almanıza olanak tanır. -
BackgroundFetchRegistration: Tek bir arka plan getirme işlemini temsil eder. Bir getirme işlemi başlattığınızda, birBackgroundFetchRegistrationnesnesi geri alırsınız. Bu nesne, getirme işlemi hakkında ID'si, toplam boyutu, indirilen bayt sayısı, durumu gibi ayrıntılar sağlar ve onunla etkileşim kurmanıza (örneğin, iptal etme) olanak tanır. Ayrıca Service Worker'a olaylar gönderir. -
BackgroundFetchEvent: Bunlar, bir arka plan getirme işleminin durumu değiştiğinde Service Worker'da tetiklenen olaylardır. Anahtar olaylar arasındabackgroundfetchsuccess(tüm kaynaklar indirildiğinde),backgroundfetchfail(getirme işlemi yeniden denemeler tükendikten sonra başarısız olduğunda),backgroundfetchabort(getirme işlemi manuel olarak iptal edildiğinde) vebackgroundfetchprogress(indirme ilerlemesi hakkında periyodik güncellemeler için) bulunur.
Arka Plan Getirme Nasıl Çalışır: Mekanizmaya Derinlemesine Bir Bakış
Arka Plan Getirme API'sinin iş akışını anlamak, etkili bir şekilde uygulanması için çok önemlidir. Bu, ana iş parçacığı (web sayfanızın JavaScript'i) ile Service Worker arasında koordineli bir çaba gerektirir.
Ana İş Parçacığından Bir Arka Plan Getirme İşlemi Başlatma
Süreç, genellikle bir kullanıcı eylemine yanıt olarak, örneğin "Filmi İndir" veya "Çevrimdışı Verileri Senkronize Et" düğmesine tıklanmasıyla ana iş parçacığında başlar. Öncelikle, Service Worker'ınızın aktif ve hazır olduğundan emin olmanız gerekir. Bu genellikle navigator.serviceWorker.ready beklenerek yapılır.
Service Worker kaydı mevcut olduğunda, backgroundFetch yöneticisine erişir ve onun fetch() metodunu çağırırsınız:
asynce function startLargeDownload(fileUrl, downloadId, title) {
if ('serviceWorker' in navigator && 'BackgroundFetchManager' in window) {
try {
const registration = await navigator.serviceWorker.ready;
const bgFetch = await registration.backgroundFetch.fetch(
downloadId, // A unique ID for this fetch
[fileUrl], // An array of Request objects or URLs to fetch
{
title: title, // Title to display in system UI/notifications
icons: [{ // Optional: Icons for system UI
src: '/images/download-icon-128.png',
sizes: '128x128',
type: 'image/png'
}],
downloadTotal: 1024 * 1024 * 500 // Optional: Total expected bytes for progress calculation (e.g., 500 MB)
}
);
console.log('Background fetch started:', bgFetch.id);
// Add event listeners to the registration object for main thread updates
bgFetch.addEventListener('progress', () => {
console.log(`Progress for ${bgFetch.id}: ${bgFetch.downloaded} of ${bgFetch.downloadTotal}`);
// Update UI here if the tab is open
});
bgFetch.addEventListener('success', () => {
console.log(`Download ${bgFetch.id} completed successfully!`);
// Notify user, update UI
});
bgFetch.addEventListener('fail', () => {
console.error(`Download ${bgFetch.id} failed.`);
// Notify user about failure
});
bgFetch.addEventListener('abort', () => {
console.warn(`Download ${bgFetch.id} was aborted.`);
});
return bgFetch;
} catch (error) {
console.error('Error starting background fetch:', error);
}
} else {
console.warn('Background Fetch API not supported.');
// Fallback to traditional download methods
window.open(fileUrl, '_blank');
}
}
// Example Usage:
// startLargeDownload('/path/to/my/large-movie.mp4', 'movie-hd-001', 'My Awesome Movie HD');
fetch() metodunun parametrelerini inceleyelim:
- `id` (String, gerekli): Bu arka plan getirme işlemi için benzersiz bir tanımlayıcı. Bu ID, getirme işlemini daha sonra almak ve yinelenen getirme işlemlerini önlemek için çok önemlidir. Kökeniniz (origin) için tüm aktif arka plan getirme işlemleri arasında benzersiz olmalıdır.
-
`requests` (`Request` nesneleri veya URL'ler dizisi, gerekli): İndirilecek kaynakları belirten bir dizi. Dize olarak basit URL'ler veya HTTP başlıklarını, metodlarını vb. özelleştirmek için daha karmaşık
Requestnesneleri geçirebilirsiniz. Çok parçalı indirmeler veya ilgili varlıkları getirmek için bu dizi birden çok giriş içerebilir. -
`options` (Object, isteğe bağlı): Arka plan getirme işlemini yapılandırmak için bir nesne. Anahtar özellikler şunları içerir:
- `title` (String): İndirme için insan tarafından okunabilir bir başlık, genellikle sistem bildirimlerinde veya tarayıcının indirme arayüzünde görüntülenir. Kullanıcının anlaması için çok önemlidir.
- `icons` (Nesne dizisi): Her biri `src`, `sizes` ve `type` özelliklerine sahip bir görüntü nesneleri dizisi. Bu ikonlar, indirmeyi görsel olarak temsil etmek için işletim sistemi tarafından kullanılır.
- `downloadTotal` (Number): İndirilmesi beklenen toplam bayt sayısı. Bu, tarayıcının sistem bildirimlerinde doğru bir ilerleme çubuğu göstermesine olanak tanıdığı için şiddetle tavsiye edilir. Sağlanmazsa, ilerleme belirsiz bir döner simge olarak gösterilir.
- `uploadTotal` (Number): `downloadTotal`'a benzer, ancak arka plan yüklemeleri için (bu rehber indirmelere odaklanmış olsa da, API her ikisini de destekler).
- `start_url` (String): Kullanıcının bu arka plan getirme işlemiyle ilişkili sistem bildirimine tıklaması durumunda yönlendirilmesi gereken isteğe bağlı bir URL.
Service Worker'da Arka Plan Getirme Olaylarını Yönetme
Asıl sihir Service Worker'da gerçekleşir. Başlatıldıktan sonra, tarayıcının ağ yığını devralır, ancak Service Worker'ınız arka plan getirme işleminin yaşam döngüsü olaylarına tepki vermekten sorumludur. Bu olaylar, indirilen verileri depolama, kullanıcıyı bilgilendirme veya hataları yönetme fırsatları sunar. Service Worker'ınızın bu belirli olaylar için olay dinleyicileri kaydetmesi gerekir:
// service-worker.js
self.addEventListener('backgroundfetchsuccess', async (event) => {
const bgFetch = event.registration;
console.log(`Background fetch ${bgFetch.id} completed successfully.`);
// Access downloaded records
const records = await bgFetch.matchAll(); // Get all fetched responses
// For simplicity, let's assume a single file download
const response = await records[0].responseReady; // Wait for the response to be ready
if (response.ok) {
// Store the downloaded content, e.g., in Cache API or IndexedDB
const cache = await caches.open('my-downloads-cache');
await cache.put(bgFetch.id, response);
console.log(`File for ${bgFetch.id} cached.`);
// Send a notification to the user
await self.registration.showNotification(bgFetch.title || 'Download Complete',
{
body: `${bgFetch.title || 'Your download'} is ready! Click to open.`,
icon: bgFetch.icons ? bgFetch.icons[0].src : '/images/default-icon.png',
data: { url: bgFetch.start_url || '/' } // Optional: URL to open on click
}
);
} else {
console.error(`Failed to get a successful response for ${bgFetch.id}`);
await self.registration.showNotification(bgFetch.title || 'Download Failed',
{
body: `There was an issue with ${bgFetch.title || 'your download'}.`,
icon: '/images/error-icon.png',
}
);
}
// Clean up the background fetch registration once handled
bgFetch.update({ status: 'completed' }); // Mark as completed
bgFetch.abort(); // Optional: Abort to clean up internal browser state if no longer needed
});
self.addEventListener('backgroundfetchfail', async (event) => {
const bgFetch = event.registration;
console.error(`Background fetch ${bgFetch.id} failed. Reason: ${bgFetch.failureReason}`);
await self.registration.showNotification(bgFetch.title || 'Download Failed',
{
body: `Unfortunately, ${bgFetch.title || 'your download'} could not be completed. Reason: ${bgFetch.failureReason || 'Unknown'}`,
icon: bgFetch.icons ? bgFetch.icons[0].src : '/images/error-icon.png',
}
);
// Implement retry logic or alert user to network issues
// Consider storing info in IndexedDB to display to user when app is next opened
});
self.addEventListener('backgroundfetchabort', async (event) => {
const bgFetch = event.registration;
console.warn(`Background fetch ${bgFetch.id} was aborted.`);
// Inform user if necessary, clean up any associated data
await self.registration.showNotification(bgFetch.title || 'Download Aborted',
{
body: `${bgFetch.title || 'Your download'} was cancelled.`,
icon: bgFetch.icons ? bgFetch.icons[0].src : '/images/warning-icon.png',
}
);
});
self.addEventListener('backgroundfetchclick', async (event) => {
const bgFetch = event.registration;
console.log(`Background fetch ${bgFetch.id} notification clicked.`);
// User clicked on the notification
if (bgFetch.start_url) {
clients.openWindow(bgFetch.start_url);
} else {
// Or open a specific page to show downloads
clients.openWindow('/downloads');
}
});
// For progress updates, the 'progress' event is also fired in the Service Worker,
// but often the main thread handles this if it's active for UI updates.
// If the main thread is not active, the Service Worker can still use this event
// for logging or more complex background processing before the 'success' event.
self.addEventListener('backgroundfetchprogress', (event) => {
const bgFetch = event.registration;
console.log(`Service Worker: Progress for ${bgFetch.id}: ${bgFetch.downloaded} of ${bgFetch.downloadTotal}`);
// You might not want to send a notification on every progress update
// but rather use it to update IndexedDB or for internal logic.
});
Her Service Worker olayını ayrıntılı olarak ele alalım:
-
backgroundfetchsuccess: Arka plan getirme işlemindeki tüm istekler başarıyla tamamlandığında tetiklenir. Bu, Service Worker'ınızın indirilen içeriği işlemesi için kritik bir olaydır. Genellikle orijinal isteklere karşılık gelenResponsenesnelerinin bir dizisini almak içinevent.registration.matchAll()kullanırsınız. Oradan, bu yanıtları çevrimdışı erişim için Cache API'sini kullanarak depolayabilir veya daha yapılandırılmış veri depolama için IndexedDB'de kalıcı hale getirebilirsiniz. İşlemden sonra, kullanıcıyı bir sistem bildirimiyle bilgilendirmek ve potansiyel olarak arka plan getirme kaydını temizlemek iyi bir uygulamadır. -
backgroundfetchfail: Arka plan getirme işlemindeki herhangi bir istek, tüm yeniden deneme girişimleri tükendikten sonra başarısız olursa tetiklenir. Bu olay, Service Worker'ınızın hataları zarif bir şekilde işlemesine, kullanıcıyı başarısızlık hakkında bilgilendirmesine ve potansiyel olarak sorun giderme adımları önermesine olanak tanır.event.registration.failureReasonözelliği, getirme işleminin neden başarısız olduğu hakkında daha fazla bağlam sağlar (örneğin, 'aborted', 'bad-status', 'quota-exceeded', 'network-error', 'none'). -
backgroundfetchabort: Arka plan getirme işlemi, uygulama tarafından programatik olarak (ana iş parçacığından veya Service Worker'dan)bgFetch.abort()kullanılarak iptal edilirse veya kullanıcı bunu tarayıcının arayüzü aracılığıyla iptal ederse tetiklenir. Bu olay, temizlik yapmak ve kullanıcıyı operasyonun durdurulduğu konusunda bilgilendirmek içindir. -
backgroundfetchclick: Kullanıcı, arka plan getirme işlemi tarafından oluşturulan bir sistem bildirimine tıkladığında tetiklenir. Bu, Service Worker'ınızın, kullanıcının yeni indirilen içeriğine erişebileceği uygulamanızda belirli bir sayfayı (örneğin, bir 'İndirilenler' bölümü) açarak yanıt vermesine olanak tanır. -
backgroundfetchprogress: İndirmenin devam eden ilerlemesini raporlamak için Service Worker'da periyodik olarak tetiklenir. Bu olay ana iş parçacığınınBackgroundFetchRegistration'ında da mevcut olsa da, Service Worker bunu arka planda günlük tutmak, kalıcı depolamayı ilerlemeyle güncellemek veya ana uygulama aktif değilse daha gelişmiş mantık için kullanabilir. Ancak, ayrıntılı kullanıcı arayüzü güncellemeleri için, genellikle bu olayı doğrudan ana iş parçacığına döndürülenBackgroundFetchRegistrationnesnesi üzerinde dinlemek, sekme açık kaldığı sürece daha verimlidir.
İlerlemeyi ve Durumu İzleme
BackgroundFetchRegistration nesnesi, devam eden veya tamamlanmış bir arka plan getirme işleminin durumuna ve ilerlemesine açılan pencerenizdir. Hem ana iş parçacığı hem de Service Worker bu bilgilere erişebilir. Ana iş parçacığında, bu nesneyi doğrudan fetch() çağrısı yaptığınızda alırsınız. Service Worker'da ise arka plan getirme olaylarında event.registration olarak mevcuttur.
BackgroundFetchRegistration'ın temel özellikleri şunlardır:
- `id` (String): Getirme işlemi başlatıldığında sağlanan benzersiz ID.
- `downloadTotal` (Number): `options` içinde belirtildiği gibi indirme için beklenen toplam bayt sayısı (veya belirtilmemişse 0).
- `downloaded` (Number): Şimdiye kadar indirilen mevcut bayt sayısı.
- `uploadTotal` (Number): Yükleme için beklenen toplam bayt sayısı (varsa).
- `uploaded` (Number): Şimdiye kadar yüklenen mevcut bayt sayısı (varsa).
- `result` (String): Getirme işlemi tamamlandığında 'success', 'failure' veya 'aborted'. Tamamlanmadan önce `null`'dır.
- `failureReason` (String): `result` 'failure' ise daha fazla ayrıntı sağlar (örneğin, 'network-error', 'quota-exceeded').
- `direction` (String): 'download' veya 'upload'.
- `status` (String): 'pending', 'succeeded', 'failed', 'aborted'. Bu, getirme işleminin mevcut durumudur.
Ayrıca BackgroundFetchManager kullanarak mevcut arka plan getirme işlemlerini de alabilirsiniz:
-
`registration.backgroundFetch.get(id)`: ID'sine göre belirli bir
BackgroundFetchRegistration'ı alır. - `registration.backgroundFetch.getIds()`: Service Worker'ınız tarafından yönetilen tüm aktif arka plan getirme ID'lerinin bir dizisine çözümlenen bir Promise döndürür.
// Main thread or Service Worker:
async function checkExistingDownloads() {
if ('serviceWorker' in navigator && 'BackgroundFetchManager' in window) {
const registration = await navigator.serviceWorker.ready;
const ids = await registration.backgroundFetch.getIds();
console.log('Active background fetch IDs:', ids);
for (const id of ids) {
const bgFetch = await registration.backgroundFetch.get(id);
if (bgFetch) {
console.log(`Fetch ID: ${bgFetch.id}, Status: ${bgFetch.status}, Progress: ${bgFetch.downloaded}/${bgFetch.downloadTotal}`);
// Attach event listeners if the current page didn't initiate it
// (useful for re-opening app and seeing ongoing fetches)
bgFetch.addEventListener('progress', () => { /* update UI */ });
bgFetch.addEventListener('success', () => { /* handle success */ });
// etc.
}
}
}
}
// checkExistingDownloads();
Pratik Kullanım Durumları ve Küresel Örnekler
Arka Plan Getirme API'si, web uygulamaları için bir dizi olasılığın kapısını aralayarak onları daha esnek, kullanıcı dostu ve küresel ölçekte yerel uygulamalarla rekabet edebilir hale getirir. İşte bazı ilgi çekici kullanım durumları:
Çevrimdışı Medya Tüketimi (Filmler, Müzik, Podcast'ler)
Hindistan'ın uzak bir köyünde internet erişiminin düzensiz ve pahalı olduğu bir kullanıcının eğitici belgeseller veya bir müzik albümü indirmek istediğini düşünün. Ya da Atlantik'i geçen uzun bir uçuşta olan bir iş seyahatçisinin, güvenilmez uçak içi Wi-Fi'ye güvenmeden önceden indirilmiş filmleri izlemek istediğini. Medya akış platformları, kullanıcıların büyük video dosyalarını, tüm podcast serilerini veya müzik albümlerini indirme sırasına almalarını sağlamak için Arka Plan Getirme'den yararlanabilir. Bu indirmeler, kullanıcı uygulamayı kapatsa bile arka planda sessizce devam edebilir ve çevrimdışı tüketime hazır hale gelebilir. Bu, çeşitli bağlantı zorluklarıyla karşı karşıya olan küresel kitleler için kullanıcı deneyimini önemli ölçüde artırır.
Büyük Dosya Senkronizasyonu ve Yedekleme (Bulut Depolama)
Bulut depolama çözümleri, çevrimiçi belge düzenleyiciler ve dijital varlık yönetim sistemleri sık sık büyük dosyalarla uğraşır - yüksek çözünürlüklü resimler, video proje dosyaları veya karmaşık elektronik tablolar. Brezilya'daki bir kullanıcının ortak bir platforma büyük bir tasarım dosyası yüklemesi veya Almanya'daki bir ekibin bir proje klasörünü senkronize etmesi, genellikle kopan bağlantılarla ilgili sorunlarla karşılaşır. Arka Plan Getirme, bu kritik yüklemelerin ve indirmelerin güvenilir bir şekilde tamamlanmasını sağlayabilir. Bir yükleme kesintiye uğrarsa, tarayıcı otomatik olarak devam edebilir, böylece değerli bilgilerle uğraşan kullanıcılar için sorunsuz veri senkronizasyonu ve iç rahatlığı sağlar.
Aşamalı Web Uygulaması (PWA) Varlık Güncellemeleri
PWA'lar uygulama benzeri deneyimler sunmak için tasarlanmıştır ve bunun bir parçası da güncel kalmaktır. Önemli çevrimdışı varlıklara sahip PWA'lar için (örneğin, büyük resim kütüphaneleri, kapsamlı istemci tarafı veritabanları veya karmaşık UI çerçeveleri), bu varlıkları güncellemek önemli bir arka plan işlemi olabilir. Kullanıcıyı bir 'güncellemeler yükleniyor' ekranında bekletmek yerine, Arka Plan Getirme bu varlık indirmelerini sessizce halledebilir. Kullanıcı, PWA'nın mevcut sürümüyle etkileşime devam edebilir ve yeni varlıklar hazır olduğunda, Service Worker bunları sorunsuz bir şekilde değiştirerek sürtünmesiz bir güncelleme deneyimi sunabilir.
Oyun İndirmeleri ve Güncellemeleri
Çevrimiçi oyunlar, tarayıcı tabanlı olanlar bile, giderek daha zengin özelliklere sahip olmakta ve genellikle önemli varlık indirmeleri (dokular, ses dosyaları, seviye verileri) gerektirmektedir. Güney Kore'deki yeni bir oyun güncellemesi bekleyen bir oyuncu veya Kanada'daki tamamen yeni bir tarayıcı tabanlı oyunu indiren bir kullanıcı, açık bir sekmeye bağlı kalmak istemez. Arka Plan Getirme, oyun geliştiricilerinin bu büyük başlangıç indirmelerini ve sonraki güncellemeleri verimli bir şekilde yönetmesini sağlar. Kullanıcılar indirmeyi başlatabilir, tarayıcılarını kapatabilir ve daha sonra tamamen güncellenmiş veya yüklenmiş bir oyuna geri dönebilir, bu da web tabanlı başlıklar için oyun deneyimini büyük ölçüde iyileştirir.
Kurumsal Veri Senkronizasyonu
Birden çok zaman diliminde ve bölgede faaliyet gösteren büyük kuruluşlar için veri senkronizasyonu çok önemlidir. Güney Afrika'daki bir satış ekibinin çevrimdışı müşteri sunumları için binlerce resim ve teknik özellik içeren kapsamlı bir ürün kataloğunu indirmesi gerektiğini veya Japonya'daki bir mühendislik firmasının devasa CAD dosyalarını senkronize ettiğini hayal edin. Arka Plan Getirme, bu görev açısından kritik veri transferleri için güvenilir bir mekanizma sağlar ve çalışanların uzaktan veya sınırlı internet altyapısına sahip alanlarda çalışırken bile her zaman en son bilgilere erişebilmelerini sağlar.
Arka Plan Getirme Uygulaması: Adım Adım Bir Kılavuz
Büyük bir dosya indirmesini yönetmek için ana iş parçacığı ve Service Worker mantığını birleştiren daha ayrıntılı bir uygulama örneğini inceleyelim.
1. Service Worker'ınızı Kaydedin
Öncelikle, Service Worker'ınızın kayıtlı ve aktif olduğundan emin olun. Bu kod genellikle ana uygulamanızın JavaScript dosyasına yerleştirilir:
// main.js
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js', { scope: '/' })
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
});
}
2. Ana İş Parçacığından Getirme İşlemini Başlatın
Bir kullanıcı büyük bir dosya indirmeye karar verdiğinde, ana uygulama mantığınız arka plan getirme işlemini tetikleyecektir. Desteklenmeyen tarayıcılar için bir geri çekilme (fallback) sağlayan bir fonksiyon oluşturalım.
// main.js (continued)
async function initiateLargeFileDownload(fileUrl, filename, fileSize) {
const downloadId = `download-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
const downloadTitle = `Downloading ${filename}`;
if ('serviceWorker' in navigator && 'BackgroundFetchManager' in window) {
try {
const registration = await navigator.serviceWorker.ready;
const bgFetch = await registration.backgroundFetch.fetch(
downloadId,
[{ url: fileUrl, headers: { 'Accept-Encoding': 'identity' } }], // Use Request object for more control
{
title: downloadTitle,
icons: [
{ src: '/images/download-icon-96.png', sizes: '96x96', type: 'image/png' },
{ src: '/images/download-icon-128.png', sizes: '128x128', type: 'image/png' }
],
downloadTotal: fileSize // Ensure this is accurate!
}
);
console.log('Background fetch initiated:', bgFetch.id);
// Attach event listeners for real-time UI updates if the tab is active
bgFetch.addEventListener('progress', (event) => {
const currentFetch = event.registration;
const percentage = Math.round((currentFetch.downloaded / currentFetch.downloadTotal) * 100);
console.log(`Main Thread: ${currentFetch.id} Progress: ${percentage}% (${currentFetch.downloaded} of ${currentFetch.downloadTotal})`);
updateDownloadProgressUI(currentFetch.id, percentage, currentFetch.downloaded, currentFetch.downloadTotal, 'downloading');
});
bgFetch.addEventListener('success', (event) => {
const currentFetch = event.registration;
console.log(`Main Thread: ${currentFetch.id} succeeded.`);
updateDownloadProgressUI(currentFetch.id, 100, currentFetch.downloaded, currentFetch.downloadTotal, 'succeeded');
showToastNotification(`'${filename}' download complete!`);
// The service worker will handle storage and actual file availability
});
bgFetch.addEventListener('fail', (event) => {
const currentFetch = event.registration;
console.error(`Main Thread: ${currentFetch.id} failed. Reason: ${currentFetch.failureReason}`);
updateDownloadProgressUI(currentFetch.id, 0, 0, currentFetch.downloadTotal, 'failed', currentFetch.failureReason);
showToastNotification(`'${filename}' download failed: ${currentFetch.failureReason}`, 'error');
});
bgFetch.addEventListener('abort', (event) => {
const currentFetch = event.registration;
console.warn(`Main Thread: ${currentFetch.id} aborted.`);
updateDownloadProgressUI(currentFetch.id, 0, 0, currentFetch.downloadTotal, 'aborted');
showToastNotification(`'${filename}' download aborted.`, 'warning');
});
// Store the background fetch ID in local storage or IndexedDB
// so that the app can re-attach to it if the user closes and re-opens the tab
storeOngoingDownload(downloadId, filename, fileSize);
} catch (error) {
console.error('Failed to initiate background fetch:', error);
fallbackDownload(fileUrl, filename);
}
} else {
console.warn('Background Fetch API not supported. Using fallback download.');
fallbackDownload(fileUrl, filename);
}
}
function updateDownloadProgressUI(id, percentage, downloaded, total, status, reason = '') {
const element = document.getElementById(`download-item-${id}`);
if (element) {
element.querySelector('.progress-bar').style.width = `${percentage}%`;
element.querySelector('.status-text').textContent = `${status.toUpperCase()}: ${percentage}% (${formatBytes(downloaded)} / ${formatBytes(total)}) ${reason ? `(${reason})` : ''}`;
// Add more complex UI updates, e.g., showing pause/cancel buttons
} else {
// Create a new UI element if this is a new download or app was just opened
createDownloadUIElement(id, percentage, downloaded, total, status, reason);
}
}
function createDownloadUIElement(id, percentage, downloaded, total, status, reason) {
const downloadsContainer = document.getElementById('downloads-list');
const itemHtml = `
${id.split('-')[0]} File
${status.toUpperCase()}: ${percentage}% (${formatBytes(downloaded)} / ${formatBytes(total)}) ${reason ? `(${reason})` : ''}
`;
downloadsContainer.insertAdjacentHTML('beforeend', itemHtml);
}
async function abortDownload(id) {
if ('serviceWorker' in navigator && 'BackgroundFetchManager' in window) {
const registration = await navigator.serviceWorker.ready;
const bgFetch = await registration.backgroundFetch.get(id);
if (bgFetch) {
await bgFetch.abort();
console.log(`Aborted fetch ${id} from UI.`);
}
}
}
function fallbackDownload(url, filename) {
const link = document.createElement('a');
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
showToastNotification(`Downloading '${filename}' via browser. Please keep tab open.`);
}
function showToastNotification(message, type = 'info') {
// Implement a simple UI toast notification system
console.log(`Toast (${type}): ${message}`);
}
function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
function storeOngoingDownload(id, filename, fileSize) {
// Using localStorage for simplicity, but IndexedDB is better for robust storage
let ongoingDownloads = JSON.parse(localStorage.getItem('ongoingDownloads') || '[]');
ongoingDownloads.push({ id, filename, fileSize, status: 'pending', downloaded: 0, total: fileSize });
localStorage.setItem('ongoingDownloads', JSON.stringify(ongoingDownloads));
}
async function loadAndMonitorExistingDownloads() {
if (!('serviceWorker' in navigator && 'BackgroundFetchManager' in window)) return;
const registration = await navigator.serviceWorker.ready;
const ids = await registration.backgroundFetch.getIds();
const storedDownloads = JSON.parse(localStorage.getItem('ongoingDownloads') || '[]');
for (const stored of storedDownloads) {
if (ids.includes(stored.id)) {
const bgFetch = await registration.backgroundFetch.get(stored.id);
if (bgFetch) {
// Re-attach listeners and update UI for existing fetches
const percentage = Math.round((bgFetch.downloaded / bgFetch.downloadTotal) * 100);
updateDownloadProgressUI(bgFetch.id, percentage, bgFetch.downloaded, bgFetch.downloadTotal, bgFetch.status);
bgFetch.addEventListener('progress', (event) => {
const currentFetch = event.registration;
const percentage = Math.round((currentFetch.downloaded / currentFetch.downloadTotal) * 100);
updateDownloadProgressUI(currentFetch.id, percentage, currentFetch.downloaded, currentFetch.downloadTotal, 'downloading');
});
// Re-attach success, fail, abort listeners as well
bgFetch.addEventListener('success', (event) => { /* ... */ });
bgFetch.addEventListener('fail', (event) => { /* ... */ });
bgFetch.addEventListener('abort', (event) => { /* ... */ });
}
} else {
// This download might have completed or failed while the app was closed
// Check bgFetch.result if available from a previous session, update UI accordingly
console.log(`Download ${stored.id} not found in active fetches, likely completed or failed.`);
// Potentially remove from local storage or mark as completed/failed
}
}
}
// Call this on app load to resume UI for ongoing downloads
// window.addEventListener('load', loadAndMonitorExistingDownloads);
İstek Başlıkları Üzerine Not: Örnekte headers: { 'Accept-Encoding': 'identity' } kullanılmıştır. Bu, ham olarak depolanacak indirmelerle uğraşırken yaygın bir uygulamadır ve sunucunun, depolamadan önce istemci tarafında geri alınması gerekebilecek içerik kodlamalarını (gzip gibi) uygulamasını engeller. Sunucu zaten sıkıştırılmamış dosyalar gönderiyorsa veya bunları sıkıştırmayı açmayı planlıyorsanız, bu gerekli olmayabilir.
3. Service Worker'da Olayları Yönetin
`service-worker.js` dosyanız daha önce açıklandığı gibi olay dinleyicilerini içerecektir. Depolama ve bildirim mantığını iyileştirelim.
// service-worker.js
// Cache names for downloads and potentially for site assets
const CACHE_NAME_DOWNLOADS = 'my-large-downloads-v1';
self.addEventListener('install', (event) => {
self.skipWaiting(); // Activate new service worker immediately
console.log('Service Worker installed.');
});
self.addEventListener('activate', (event) => {
event.waitUntil(clients.claim()); // Take control of existing clients
console.log('Service Worker activated.');
});
// backgroundfetchsuccess: Store content and notify user
self.addEventListener('backgroundfetchsuccess', async (event) => {
const bgFetch = event.registration;
console.log(`SW: Background fetch ${bgFetch.id} succeeded.`);
let downloadSuccessful = true;
try {
const records = await bgFetch.matchAll();
const cache = await caches.open(CACHE_NAME_DOWNLOADS);
for (const record of records) {
const response = await record.responseReady;
if (response.ok) {
// Use a unique cache key, e.g., the original URL or bgFetch.id + a counter
await cache.put(record.request.url, response.clone()); // Clone is important as response can only be consumed once
console.log(`SW: Stored ${record.request.url} in cache.`);
} else {
console.error(`SW: Failed to get successful response for ${record.request.url}. Status: ${response.status}`);
downloadSuccessful = false;
// Potentially remove partially downloaded files or mark as failed
break; // Stop processing if one part failed
}
}
if (downloadSuccessful) {
await self.registration.showNotification(bgFetch.title || 'Download Complete',
{
body: `${bgFetch.title || 'Your download'} is now available offline!`,
icon: bgFetch.icons ? bgFetch.icons[0].src : '/images/default-icon.png',
badge: '/images/badge-icon.png', // Optional: Small icon for taskbar/status bar
data: { bgFetchId: bgFetch.id, type: 'download-complete' },
actions: [
{ action: 'open-download', title: 'Open', icon: '/images/open-icon.png' },
{ action: 'delete-download', title: 'Delete', icon: '/images/delete-icon.png' }
]
}
);
// Optional: Update IndexedDB to mark download as complete
} else {
// Handle scenario where not all parts succeeded
await self.registration.showNotification(bgFetch.title || 'Download Partial/Failed',
{
body: `Part of ${bgFetch.title || 'your download'} could not be completed. Please check.`,
icon: '/images/error-icon.png',
}
);
}
} catch (error) {
console.error(`SW: Error during backgroundfetchsuccess for ${bgFetch.id}:`, error);
downloadSuccessful = false;
await self.registration.showNotification(bgFetch.title || 'Download Error',
{
body: `An unexpected error occurred with ${bgFetch.title || 'your download'}.`,
icon: '/images/error-icon.png',
}
);
}
// After handling, cleanup the background fetch registration
// The spec recommends not calling abort() immediately after success/fail
// if you want to keep the registration active for monitoring or historical data.
// However, if the download is truly done and its data stored, you might clear it.
// For this example, let's consider it handled.
});
// backgroundfetchfail: Notify user about failure
self.addEventListener('backgroundfetchfail', async (event) => {
const bgFetch = event.registration;
console.error(`SW: Background fetch ${bgFetch.id} failed. Reason: ${bgFetch.failureReason}`);
await self.registration.showNotification(bgFetch.title || 'Download Failed',
{
body: `Unfortunately, ${bgFetch.title || 'your download'} could not be completed. Reason: ${bgFetch.failureReason || 'Unknown'}`,
icon: bgFetch.icons ? bgFetch.icons[0].src : '/images/error-icon.png',
badge: '/images/error-badge.png',
data: { bgFetchId: bgFetch.id, type: 'download-failed' }
}
);
// Optional: Update IndexedDB to mark download as failed, potentially offering a retry option
});
// backgroundfetchabort: Notify user about cancellation
self.addEventListener('backgroundfetchabort', async (event) => {
const bgFetch = event.registration;
console.warn(`SW: Background fetch ${bgFetch.id} was aborted.`);
// Optionally remove partial downloads from cache/IndexedDB
await self.registration.showNotification(bgFetch.title || 'Download Aborted',
{
body: `${bgFetch.title || 'Your download'} was cancelled.`,
icon: bgFetch.icons ? bgFetch.icons[0].src : '/images/warning-icon.png',
data: { bgFetchId: bgFetch.id, type: 'download-aborted' }
}
);
});
// notificationclick: Handle user interaction with notifications
self.addEventListener('notificationclick', (event) => {
const notification = event.notification;
const primaryClient = clients.matchAll({ type: 'window', includeUncontrolled: true }).then(clientList => {
for (const client of clientList) {
if (client.url.startsWith(self.location.origin) && 'focus' in client) {
return client.focus();
}
}
return clients.openWindow(notification.data.url || '/downloads');
});
event.waitUntil(primaryClient);
// Handle notification actions (e.g., 'Open', 'Delete')
if (event.action === 'open-download') {
event.waitUntil(clients.openWindow('/downloads'));
} else if (event.action === 'delete-download') {
// Implement logic to delete the downloaded file from cache/IndexedDB
// and update the main thread UI if active.
const bgFetchIdToDelete = notification.data.bgFetchId;
// Example: Delete from Cache API
caches.open(CACHE_NAME_DOWNLOADS).then(cache => {
cache.delete(bgFetchIdToDelete); // Or the specific URL associated with the ID
console.log(`SW: Deleted download for ${bgFetchIdToDelete} from cache.`);
});
notification.close();
}
});
// backgroundfetchprogress: Use for internal logic or less frequent updates if main thread is not active
self.addEventListener('backgroundfetchprogress', (event) => {
const bgFetch = event.registration;
console.log(`SW: Progress for ${bgFetch.id}: ${bgFetch.downloaded} of ${bgFetch.downloadTotal}`);
// Here you could update IndexedDB with progress for persistent state,
// but typically, progress notifications to the user are handled by the OS/browser.
});
4. Kullanıcıya İlerlemeyi Gösterme (Ana İş Parçacığı ve Bildirimler)
Ana iş parçacığı kodunda gösterildiği gibi, bgFetch.addEventListener('progress', ...) sekme açıkken uygulamanın kullanıcı arayüzünü güncellemek için çok önemlidir. Arka plan işlemleri için, Service Worker'daki self.registration.showNotification() tarafından tetiklenen tarayıcının yerel sistem bildirimleri, tarayıcı kapalı veya simge durumuna küçültülmüş olsa bile ilerleme güncellemeleri ve uyarılar sağlar. Bu ikili yaklaşım, kullanıcıların uygulamayla aktif etkileşimlerinden bağımsız olarak harika bir kullanıcı deneyimi sağlar.
Kullanıcı arayüzünüzü indirme ilerlemesini zarif bir şekilde gösterecek, kullanıcıların getirme işlemlerini iptal etmelerine izin verecek ve tamamlanmış veya başarısız indirmelerin durumunu gösterecek şekilde tasarlamak hayati önem taşır. PWA'nızda kullanıcıların tüm arka plan getirme etkinliklerini gözden geçirebilecekleri özel bir "İndirilenler" bölümü düşünün.
5. İndirilen İçeriği Alma
Bir arka plan getirme işlemi başarılı olduğunda ve Service Worker içeriği (örneğin, Cache API veya IndexedDB'de) depoladığında, ana uygulamanızın ona erişmek için bir yola ihtiyacı vardır. Cache API'sinde depolanan içerik için, `Response` nesnesini almak üzere standart caches.match() veya caches.open() kullanabilirsiniz. IndexedDB için, depolanan verilerinizi sorgulamak üzere API'sini kullanırsınız.
// main.js (example for retrieving cached content)
async function getDownloadedFile(originalUrl) {
if ('caches' in window) {
const cache = await caches.open(CACHE_NAME_DOWNLOADS);
const response = await cache.match(originalUrl);
if (response) {
console.log(`Retrieved ${originalUrl} from cache.`);
// Now you can work with the response, e.g., create an Object URL for display
const blob = await response.blob();
return URL.createObjectURL(blob);
} else {
console.log(`${originalUrl} not found in cache.`);
return null;
}
}
return null;
}
// Example: Display a downloaded video
// const videoUrl = await getDownloadedFile('/path/to/my/large-movie.mp4');
// if (videoUrl) {
// const videoElement = document.getElementById('my-video-player');
// videoElement.src = videoUrl;
// videoElement.play();
// }
İleri Düzey Hususlar ve En İyi Uygulamalar
Arka Plan Getirme API'si ile gerçekten sağlam ve kullanıcı dostu bir deneyim oluşturmak için bu ileri düzey konuları ve en iyi uygulamaları göz önünde bulundurun:
Hata Yönetimi ve Yeniden Deneme Mekanizmaları
API doğal olarak bazı yeniden deneme mantığı sağlar, ancak uygulamanız çeşitli başarısızlık senaryolarına hazırlıklı olmalıdır. Bir `backgroundfetchfail` olayı meydana geldiğinde, event.registration.failureReason özelliği paha biçilmezdir. Olası nedenler arasında 'network-error', 'bad-status' (örneğin, 404 veya 500 HTTP yanıtı), 'quota-exceeded' (tarayıcının depolama alanı biterse) veya 'aborted' bulunur. Service Worker'ınız şunları yapabilir:
- Hataları Günlüğe Kaydetme: Performansı izlemek ve dünya genelindeki yaygın başarısızlık noktalarını belirlemek için hata ayrıntılarını analitik veya günlük hizmetinize gönderin.
- Kullanıcı Bildirimi: Kalıcı bildirimler aracılığıyla başarısızlık nedenini kullanıcıya açıkça iletin.
- Yeniden Deneme Mantığı: `network-error` için, kullanıcıya bağlantısını kontrol etmesini önerebilirsiniz. `bad-status` için, destekle iletişime geçmesini tavsiye edebilirsiniz. `quota-exceeded` için, yer açmasını önerin. Tarayıcı temel yeniden denemeleri dahili olarak yönetse de, uygunsa akıllı bir yeniden deneme mekanizması (örneğin, üstel geri çekilme) uygulayın.
- Temizlik: Yer açmak için başarısız getirme işlemleriyle ilişkili kısmi dosyaları veya geçici verileri kaldırın.
Kullanıcı Arayüzü Geri Bildirimi ve Bildirimler
Kullanıcı ile etkili iletişim her şeyden önemlidir. Bu şunları içerir:
- İlerleme Çubukları: Aktifken web sayfasında dinamik ilerleme çubukları ve arka plan ilerlemesi için sistem düzeyinde bildirimler ( `downloadTotal` belirtilmiş olarak).
- Durum Göstergeleri: "İndiriliyor," "Duraklatıldı," "Başarısız," "Tamamlandı" veya "İptal Edildi" belirten net simgeler veya metinler.
- Eyleme Geçirilebilir Bildirimler: Kullanıcıların bir indirmeyi doğrudan sistem bildiriminden "Açmasına", "Silmesine" veya "Yeniden Denemesine" olanak tanımak için bildirim eylemlerini (`showNotification` içindeki `actions` dizisi) kullanarak rahatlığı artırın.
- Kalıcı İndirme Listesi: PWA'nızda (örneğin, '/downloads') kullanıcıların geçmiş ve devam eden tüm arka plan getirme işlemlerinin durumunu görüntüleyebileceği, başarısız olanları yeniden başlatabileceği veya indirilen içeriği yönetebileceği özel bir bölüm. Bu, özellikle bağlantıları istikrarsız olan ve indirmeleri sık sık yeniden ziyaret edebilecek bölgelerdeki kullanıcılar için önemlidir.
Bant Genişliği ve Kaynak Yönetimi
Özellikle verinin pahalı veya sınırlı olduğu bölgelerde kullanıcı bant genişliğine dikkat edin. Arka Plan Getirme API'si verimli olacak şekilde tasarlanmıştır, ancak şunları yaparak daha da optimize edebilirsiniz:
- Kullanıcı Tercihlerine Saygı Gösterme: Ağ koşullarını ve kullanıcının veri tasarrufu tercihini belirlemek için
navigator.connection.effectiveTypeveyanavigator.connection.saveData'yı kontrol edin. Yavaş veya tarifeli ağlarda daha düşük kaliteli indirmeler sunun veya büyük transferlerden önce onay isteyin. - İstekleri Gruplama: Birden çok küçük dosya için, birçok bireysel getirme işlemi başlatmak yerine bunları tek bir arka plan getirme işleminde gruplamak genellikle daha verimlidir.
- Önceliklendirme: Birden çok dosya indiriyorsanız, önce kritik içeriği önceliklendirmeyi düşünün.
- Disk Kota Yönetimi: Tarayıcının depolama kotalarından haberdar olun. Çok fazla indirmeye çalışırsanız `quota-exceeded` `failureReason` tetiklenir. Eski indirmeleri temizlemelerine izin vermek gibi depolamayı yönetmek için stratejiler uygulayın.
Çevrimdışı Depolama (IndexedDB, Cache API)
Arka Plan Getirme API'si ağ isteğini yönetir, ancak alınan `Response` nesnelerini depolamaktan siz sorumlusunuz. İki ana mekanizma şunlardır:
-
Cache API: Statik varlıkları, medya dosyalarını veya doğrudan bir URL'ye eşlenebilen herhangi bir yanıtı depolamak için idealdir.
caches.open().put(request, response)ile kullanımı basittir. - IndexedDB: Büyük miktarda yapılandırılmış verinin istemci tarafında depolanması için güçlü, düşük seviyeli bir API. Bunu daha karmaşık veri şemaları, indirmelerle ilişkili meta veriler veya sağlam sorgulama yeteneklerine ihtiyacınız olduğunda kullanın. Örneğin, indirilen bir videonun meta verilerini (başlık, uzunluk, açıklama, indirme tarihi) ikili verileriyle (Blob olarak) birlikte depolamak. Dexie.js gibi kütüphaneler IndexedDB etkileşimlerini basitleştirebilir.
Genellikle her ikisinin bir kombinasyonu faydalıdır: Ham indirilen içerik için Cache API ve meta verileri, indirme durumlarını ve tüm getirme işlemlerinin bir listesini yönetmek için IndexedDB.
Güvenlik Etkileri
Tüm güçlü web API'lerinde olduğu gibi, güvenlik her şeyden önemlidir:
- Sadece HTTPS: Service Worker'lar ve dolayısıyla Arka Plan Getirme API'si güvenli bir bağlam (HTTPS) gerektirir. Bu, veri bütünlüğünü sağlar ve ortadaki adam saldırılarını önler.
- Aynı Köken Politikası (Same-Origin Policy): Farklı kökenlerden kaynaklar getirebilseniz de, Service Worker'ın kendisi web sitenizin aynı köken politikası kısıtlamaları dahilinde çalışır. İndirdiğiniz içerik ve onu nasıl işlediğiniz konusunda dikkatli olun.
- İçerik Doğrulaması: Özellikle kullanıcı tarafından oluşturulmuşsa veya güvenilmeyen kaynaklardan geliyorsa, indirilen içeriği işlemeden veya görüntülemeden önce daima doğrulayın.
Tarayıcı Uyumluluğu ve Geri Çekilmeler (Fallbacks)
Arka Plan Getirme API'si nispeten yeni ve güçlü bir özelliktir. 2023 sonu / 2024 başı itibarıyla, öncelikle Chromium tabanlı tarayıcılarda (Chrome, Edge, Opera, Samsung Internet) iyi desteklenmektedir. Firefox ve Safari henüz uygulamamıştır veya değerlendirme aşamasındadır. Küresel bir kitle için, sağlam geri çekilmeler uygulamak çok önemlidir:
- Özellik Tespiti: API'yi kullanmaya çalışmadan önce daima
'serviceWorker' in navigatorve'BackgroundFetchManager' in windowolup olmadığını kontrol edin. - Geleneksel İndirmeler: Arka Plan Getirme desteklenmiyorsa, standart bir tarayıcı indirmesi başlatmaya geri dönün (örneğin, bir `download` özniteliğine sahip bir `<a>` etiketi oluşturarak ve bir tıklamayı tetikleyerek). Kullanıcıya sekmeyi açık tutmaları gerektiğini bildirin.
- Aşamalı Geliştirme: Uygulamanızı, temel işlevselliğin Arka Plan Getirme olmadan çalışacağı ve API'nin yalnızca desteklenen tarayıcılar için deneyimi geliştireceği şekilde tasarlayın.
Test ve Hata Ayıklama
Service Worker'ları ve arka plan süreçlerini hata ayıklamak zor olabilir. Tarayıcı geliştirici araçlarını kullanın:
- Chrome DevTools: "Application" sekmesi, Service Worker'lar (kaydı izleme, başlatma/durdurma, olayları gönderme), Cache Storage ve IndexedDB için bölümler sağlar. Arka Plan Getirme işlemleri de özel bir "Background Services" veya "Application" bölümü altında (genellikle "Background fetches" altında) görülebilir.
- Günlük Kaydı (Logging): Hem ana iş parçacığınızda hem de Service Worker'ınızda kapsamlı `console.log` ifadeleri, olayların akışını anlamak için esastır.
- Olayları Simüle Etme: Bazı tarayıcı DevTools'ları, arka plan mantığını test etmek için yararlı olabilecek Service Worker olaylarını (örneğin, 'sync' veya 'push') manuel olarak tetiklemenize olanak tanır, ancak arka plan getirme olaylarının doğrudan simülasyonu sınırlı olabilir ve genellikle gerçek ağ etkinliğine dayanır.
Geleceğe Bakış ve İlgili Teknolojiler
Arka Plan Getirme API'si, genellikle Project Fugu (veya "Yetenekler Projesi") gibi girişimler altında gruplanan, web platformuna daha güçlü yetenekler getirme çabasının bir parçasıdır. Bu proje, güvenli ve gizliliği koruyan bir şekilde daha fazla cihaz donanımı ve işletim sistemi özelliğini web'e sunarak web uygulamaları ile yerel uygulamalar arasındaki boşluğu kapatmayı amaçlamaktadır. Web geliştikçe, çevrimdışı yetenekleri, sistem entegrasyonunu ve performansı artıran bu türden daha fazla API bekleyebiliriz.
Web Yetenekleri ve Project Fugu
Arka Plan Getirme API'si, web uygulamalarının yapabileceklerinin sınırlarını zorlayan bir web yeteneğinin en iyi örneğidir. Project Fugu kapsamındaki kullanıcı deneyimini ve çevrimdışı yetenekleri artıran diğer ilgili API'ler şunları içerir:
- Periyodik Arka Plan Senkronizasyonu (Periodic Background Sync): Düzenli olarak küçük miktarda veri senkronizasyonu için.
- Web Paylaşım API'si (Web Share API): Cihazdaki diğer uygulamalarla içerik paylaşmak için.
- Dosya Sistemi Erişim API'si (File System Access API): Kullanıcının yerel dosya sistemiyle daha doğrudan etkileşim için (açık kullanıcı izniyle).
- Rozetleme API'si (Badging API): Uygulama simgelerinde okunmamış sayıları veya durumu göstermek için.
Bu API'ler toplu olarak, geliştiricilere işlevsellik ve kullanıcı deneyimi açısından yerel uygulamalardan ayırt edilemeyen web uygulamaları oluşturma gücü vermeyi amaçlamaktadır; bu da çeşitli cihaz tercihleri ve yeteneklerine sahip küresel bir kitle için önemli bir kazançtır.
Workbox Entegrasyonu
Birçok geliştirici için doğrudan Service Worker API'leriyle çalışmak karmaşık olabilir. Workbox gibi kütüphaneler, önbellekleme stratejileri ve arka plan senkronizasyonu dahil olmak üzere yaygın Service Worker kalıplarını basitleştirir. Workbox'ın henüz özellikle Arka Plan Getirme için doğrudan bir modülü olmasa da, Service Worker'ınızı yönetmek için sağlam bir temel sağlar ve özel Arka Plan Getirme uygulamanızla birlikte kullanılabilir. API olgunlaştıkça, bu tür kütüphanelerle daha yakın entegrasyon görebiliriz.
Diğer API'lerle Karşılaştırma (Fetch, XHR, Streams)
Arka Plan Getirme'nin diğer ağ API'lerine kıyasla nerede durduğunu anlamak önemlidir:
- Standart `fetch()` ve XHR: Bunlar, aktif tarayıcı sekmesine bağlı kısa ömürlü, senkron (veya promise tabanlı asenkron) istekler içindir. Çoğu veri getirme işlemi için uygundurlar ancak sekme kapanırsa veya ağ koparsa başarısız olurlar. Arka Plan Getirme, kalıcı, uzun süren görevler içindir.
- Streams API: Büyük yanıtları parça parça işlemek için kullanışlıdır ve `fetch()` veya Arka Plan Getirme ile birleştirilebilir. Örneğin, bir `backgroundfetchsuccess` olayı bir yanıt alabilir ve ardından tüm blob'un bellekte olmasını beklemek yerine indirilen içeriği artımlı olarak işlemek için okunabilir akışlar kullanabilir. Bu, özellikle çok büyük dosyalar veya gerçek zamanlı işleme için kullanışlıdır.
Arka Plan Getirme, güvenilir arka plan aktarımı için temel mekanizmayı sağlayarak bu API'leri tamamlar; `fetch()` (veya XHR) daha küçük, ön plan etkileşimleri için kullanılabilirken, Streams her ikisi aracılığıyla elde edilen verilerin verimli bir şekilde işlenmesi için kullanılabilir. Anahtar ayrım, Arka Plan Getirme'nin "arka plan" ve "kalıcı" doğasıdır.
Sonuç: Sağlam Frontend İndirmelerini Güçlendirmek
Frontend Arka Plan Getirme API'si, web geliştirmede önemli bir ileri adımı temsil eder ve büyük dosyaların istemci tarafında nasıl ele alındığını temelden değiştirir. Sekme kapanmalarına ve ağ kesintilerine dayanabilen gerçekten kalıcı ve güvenilir indirmeleri etkinleştirerek, geliştiricilere yerel benzeri bir deneyim sunan Aşamalı Web Uygulamaları oluşturma gücü verir. Bu sadece teknik bir gelişme değil; birçoğu kesintili veya daha az güvenilir internet bağlantılarına dayanan küresel bir kitle için kritik bir kolaylaştırıcıdır.
Gelişmekte olan pazarlarda sorunsuz çevrimdışı medya tüketiminden kıtalar arasında sağlam kurumsal veri senkronizasyonuna kadar, Arka Plan Getirme daha dayanıklı ve kullanıcı dostu bir web'in yolunu açar. Özellikle hata yönetimi, kullanıcı geri bildirimi ve depolama yönetimi konusunda dikkatli bir uygulama gerektirse de, gelişmiş kullanıcı deneyimi ve uygulama güvenilirliği açısından faydaları çok büyüktür. Tarayıcı desteği genişlemeye devam ettikçe, Arka Plan Getirme API'sini web uygulamalarınıza entegre etmek, dünyanın her yerindeki kullanıcılara birinci sınıf dijital deneyimler sunmak için vazgeçilmez bir strateji haline gelecektir.